{# Base layout every page extends. Blocks: title, favicon, head_extra, navbar, page_body, content, footer, scripts. Override ``content`` for an ordinary page; reach for ``page_body`` only when a page needs to replace the whole main wrapper. #} {% block title %}{{ project_name }}{% endblock %} {# Favicon: SVG only. Modern browsers handle it natively (auto-scales, respects prefers-color-scheme inside the SVG, and the bytes are smaller than maintaining a multi-resolution ICO). Older browsers and bots that auto-request /favicon.ico will 404 — harmless. #} {% block favicon %}{% endblock %} {# Tailwind + DaisyUI, precompiled — no runtime JIT, no CDN. Built into static/dist by the asset pipeline; static() returns the fingerprinted URL once a build exists and the raw source path before then. #} {# htmx. History snapshots are disabled deliberately: htmx's default back-button behavior saves the live DOM to localStorage and re-injects it on history navigation. This DOM is full of Alpine-expanded templates (x-if/x-for clones, x-teleport copies) and script tags — restoring a snapshot re-runs scripts ("identifier already declared") and makes Alpine re-expand already-expanded templates, duplicating the whole page once per back/forward press. historyCacheSize 0 makes every restore a cache miss; refreshOnHistoryMiss turns a miss into a clean full-page load instead of an AJAX restore. #} {# Alpine.js — the collapse plugin MUST load before core so its directive is registered when Alpine inits. Both deferred, plugin first. #} {# Custom styles #} {% block head_extra %}{% endblock %} {% block navbar %}
{{ project_name }} Dashboard
{% endblock %} {% block page_body %}
{% block content %}{% endblock %}
{% endblock %} {% block footer %}{% endblock %} {% include "components/snackbar.html" %} {% if auth_enabled %}{% endif %} {% block scripts %}{% endblock %}